package com.study.algorithm.ordinaryArray;

import java.util.Arrays;

public class Rotate {
    //方法一，使用额外数组
    public void rotate(int[] nums, int k) {
        int n = nums.length;
        int[] temp = new int[n];//额外数组
        for (int i = 0; i < n; i++) {
            temp[(i + k) % n] = nums[i];
        }
        System.arraycopy(temp, 0, nums, 0, n);
    }

    //方法二，三次翻转法
    public void rotate2(int[] nums, int k) {
        k %= nums.length; //避免k超过数组长度
        reverse(nums, 0, nums.length - 1);//翻转整个数组
        reverse(nums, 0, k - 1);//翻转前k个元素
        reverse(nums, k, nums.length - 1);//翻转剩余元素
    }

    //反转数组
    private void reverse(int[] nums, int start, int end) {
        while (start < end) {
            int temp = nums[start];
            nums[start] = nums[end]; //start->end
            nums[end] = temp; //end->start
            start++;
            end--;
        }
    }

    //方法三，环状替换法
    public void rotate3(int[] nums, int k) {
        //1.计算有效旋转次数，避免k超过数组长度
        k %= nums.length;
        //2.初始化计数器，记录已处理的元素数量
        int count = 0;
        //3.遍历数组，找到每个元素对应的位置
        for(int start = 0; count < nums.length; start++){
            int current = start; //处理的当前元素
            int prev = nums[start]; //当前元素的元素值
            //4.开始环状替换
            do{
                int next = (current + k) % nums.length;//下一个元素位置
                int temp = nums[next];//下一个元素值
                nums[next] = prev; //把当前元素值赋给下一个元素
                prev = temp;//把下一个元素值赋给当前元素

                current = next;//当前元素位置
                count++;//移动次数累加
            }while(current != start);
        }
    }

    public static void main(String[] args) {
        int[] nums = {1, 2, 3, 4, 5};
        Rotate rotate = new Rotate();
   /*     rotate.rotate(nums, 3);
        System.out.println(Arrays.toString(nums));*/
/*        rotate.rotate2(nums, 3);
        System.out.println(Arrays.toString(nums));*/
        rotate.rotate3(nums, 2);
        System.out.println(Arrays.toString(nums));

    }
}
